package com.ymall.task;

import com.ymall.common.Const;
import com.ymall.common.RedisShardedPool;
import com.ymall.common.RedissonManager;
import com.ymall.service.ClockService;
import com.ymall.util.JedisShardedUtil;
import com.ymall.util.PropertiesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * Created by EvenLee on 2018/1/14.
 */
@Component
@Slf4j
public class CloseOrderTask {

    @Autowired
    ClockService clockService;

    @Autowired
    RedissonManager redissonManager;

    public void runVersion1(){
        //:TODO real Task
        int hour = Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2"));
        clockService.clockIn (null);
    }

    public void runVersion2(){
        //锁定时间（锁定时间超过任务执行时间）
        Long lockTime = Long.parseLong (PropertiesUtil.getProperty ("redis.lock.time","5000"));
        Long setnxResult = JedisShardedUtil.setnx (Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK, String.valueOf (System.currentTimeMillis ()+lockTime));
        if (setnxResult !=null&&setnxResult ==1){
            //:TODO real Task
            closeOrder (Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
        }else {
            log.info("没有获得分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
        }
    }

    public void runVersion3(){
        Long lockTime = Long.parseLong (PropertiesUtil.getProperty ("redis.lock.time","5000"));
        Long setnxResult = JedisShardedUtil.setnx (Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK, String.valueOf (System.currentTimeMillis ()+lockTime));
        if (setnxResult !=null&&setnxResult ==1){
            log.info ("INFO: do somethings !");
        }else {
            String lockValueStr = JedisShardedUtil.get(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);

            if (lockValueStr != null && System.currentTimeMillis () > Long.parseLong (lockValueStr) ){
                String getSetnxValue = JedisShardedUtil.get (Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
                if (getSetnxValue == null||(getSetnxValue != null&& StringUtils.equals (getSetnxValue,lockValueStr))){
                    //:TODO real Task
                    closeOrder (Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
                }else {
                    log.info("没有获得分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
                }
            }else {
                log.info("没有获得分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
            }
        }
    }
    @Scheduled(cron = "0 */10 * * * ?")
    public void runVersion4() throws InterruptedException{
        RLock lock = redissonManager.getRedisson ().getLock (Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
        boolean getLock = false;
        try {
            if (getLock = lock.tryLock (0,50, TimeUnit.SECONDS)){
                log.info ("获取到了锁");
                int hour = Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2"));
                clockService.clockIn (null);
            }else {
                log.info("没有获得分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
            }
        }finally {
            if (!getLock){
                return;
            }
            lock.unlock ();
        }

    }
    private void closeOrder(String lockName){
//        expire命令用于给该锁设定一个过期时间，用于防止线程crash，导致锁一直有效，从而导致死锁。
        JedisShardedUtil.expire(lockName,5);//有效期50秒,防死锁
        log.info("获取{},ThreadName:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,Thread.currentThread().getName());
        int hour = Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2"));
        clockService.clockIn (null);
        JedisShardedUtil.del(lockName);//释放锁
        log.info("释放{},ThreadName:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,Thread.currentThread().getName());
        log.info("=============================");
    }

}
